package com.mti.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mti.component.snowflake.KeyWorker;
import com.mti.configuration.SystemConfig;
import com.mti.constant.YjHandleStatusCode;
import com.mti.constant.ZdryYjLx;
import com.mti.dao.dto.ResultDto;
import com.mti.dao.dto.ZdryYjHandlePushDto;
import com.mti.dao.model.KmZdryTypeEntity;
import com.mti.dao.model.LfZtryyjEntity;
import com.mti.dao.model.TKmYjHandleEntity;
import com.mti.dao.model.TTaskFileEntity;
import com.mti.dao.qo.TkmYjHanQo;
import com.mti.dao.vo.TKmYjHandleVo;
import com.mti.exception.BusinessException;
import com.mti.jwt.AccountBo;
import com.mti.jwt.RequestUtils;
import com.mti.mapper.TKmYjHandleMapper;
import com.mti.service.ILfZtryyjsjService;
import com.mti.service.KmZdryTypeService;
import com.mti.service.TKmYjHandleService;
import com.mti.service.TTaskFileService;
import com.mti.utils.DateUtils;
import com.mti.websocket.SocketType;
import com.mti.websocket.WebSocketUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DefaultDataBuffer;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 预警处置表 服务实现类
 * </p>
 *
 * @author duchaof
 * @since 2020-03-11
 */
@Slf4j
@Service
public class TKmYjHandleServiceImpl extends ServiceImpl<TKmYjHandleMapper, TKmYjHandleEntity> implements TKmYjHandleService {
    @Resource
    private TTaskFileService tTaskFileService;
    @Resource
    private ILfZtryyjsjService iLfZtryyjsjService;
    @Resource
    private WebSocketUtils webSocketUtils;
    @Resource
    private KmZdryTypeService kmZdryTypeService;
    @Resource
    private RequestUtils requestUtils;
    @Resource
    private RestTemplate restTemplate;
    @Resource
    private SystemConfig systemConfig;

    private static final List<String> exectTitle = Arrays.asList("姓名", "预警时间", "预警方式","风险等级","预警位置", "身份证号", "户籍地",
            "人员大类", "人员小类", "管控单位", "管控民警", "是否处置", "处置时间", "处置结果");

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addTKmYjHandle(List<TKmYjHandleEntity> tKmYjHandleEntityList, ServerWebExchange exchange) {
        boolean result = false;
        if (null != tKmYjHandleEntityList && tKmYjHandleEntityList.size() > 0) {
            for (TKmYjHandleEntity tKmYjHandleEntity : tKmYjHandleEntityList) {
                tKmYjHandleEntity.setId(String.valueOf(KeyWorker.nextId()));
                AccountBo bo = requestUtils.getCurrentUser(exchange);
                if (bo == null) {
                    throw new BusinessException(10019, "此账号已在别处登录，请查证");
                }
                if (null != bo.getPersonBo()) {
                    tKmYjHandleEntity.setHandlePolice(bo.getPersonBo().getName()); //处置民警
                }
                if (null != bo.getOrganizationBo()) {
                    tKmYjHandleEntity.setPoliceStation(bo.getOrganizationBo().getShortName());
                    tKmYjHandleEntity.setPoliceStationId(bo.getOrganizationBo().getId());
                }
                result = this.save(tKmYjHandleEntity);
                if (null != tKmYjHandleEntity.getFiles() && tKmYjHandleEntity.getFiles().size() > 0) {
                    for (TTaskFileEntity file : tKmYjHandleEntity.getFiles()) {
                        file.setId(String.valueOf(KeyWorker.nextId()));
                        file.setBussType("4");
                        file.setBussId(tKmYjHandleEntity.getId());
                        tTaskFileService.save(file);
                    }
                }
                // 修改预警处置标志
                LfZtryyjEntity lfZtryyjEntity = new LfZtryyjEntity();
                lfZtryyjEntity.setWybs(tKmYjHandleEntity.getRefId());
                lfZtryyjEntity.setHandleFlag(2);
                boolean updateRes = iLfZtryyjsjService.updateById(lfZtryyjEntity);

                ZdryYjHandlePushDto zdryYjHandlePushDto = new ZdryYjHandlePushDto();
                zdryYjHandlePushDto.setNotificationID(tKmYjHandleEntity.getRefId());
                zdryYjHandlePushDto.setAlarmStatus(YjHandleStatusCode.Controlled_True.getStatus());
                zdryYjHandlePushDto.setFeedbackTime(DateUtils.dateToString(tKmYjHandleEntity.getHandleTime(), "yyyy-MM-dd HH:mm:ss"));
                zdryYjHandlePushDto.setFeedbackRemark(tKmYjHandleEntity.getHandleContent());
                zdryYjHandlePushDto.setFeedbackPerson(tKmYjHandleEntity.getHandlePolice());
                ResultDto resultDto = pushYjHandleResultToKd(zdryYjHandlePushDto);
                //添加成功后发送websocket
                if (updateRes) {
                    List<String> tokens = iLfZtryyjsjService.findWebsocketPsuhUserListByYjwybs(tKmYjHandleEntity.getRefId());
                    if (null != tokens) {
                        webSocketUtils.sendWebsockMessageToUser(tokens,
                                Arrays.asList("新增预警处置信息"), SocketType.ZDRRYJXX.getName());
                    }
                }
            }
        }
        return result;
    }

    @Override
    @Transactional
    public boolean deleteTKmYjHandle(String id) {
        boolean result = this.removeById(id);
        if (result) {
            tTaskFileService.remove(new QueryWrapper<TTaskFileEntity>().lambda().eq(TTaskFileEntity::getBussId, id));
        }
        return result;
    }

    @Override
    @Transactional
    public boolean updateTKmYjHandle(TKmYjHandleEntity tKmYjHandleEntity) {
        boolean result = this.updateById(tKmYjHandleEntity);
        if (result) {
            tTaskFileService.remove(new QueryWrapper<TTaskFileEntity>().lambda()
                    .eq(TTaskFileEntity::getBussId, tKmYjHandleEntity.getId()));
        }
        if (null != tKmYjHandleEntity.getFiles() && tKmYjHandleEntity.getFiles().size() > 0) {
            for (TTaskFileEntity file : tKmYjHandleEntity.getFiles()) {
                file.setId(String.valueOf(KeyWorker.nextId()));
                file.setBussType("4");
                file.setBussId(tKmYjHandleEntity.getId());
                tTaskFileService.save(file);
            }
        }
        return result;
    }

    @Override
    public List<TKmYjHandleVo> listTKmYjHandle(TkmYjHanQo tkmYjHanQo) {
        List<TKmYjHandleVo> result = this.getBaseMapper().listTKmYjHandle(tkmYjHanQo);
        handleTKmYjInfo(result);
        return result;
    }

    @Override
    public IPage<TKmYjHandleVo> pageTKmYjHandle(TkmYjHanQo tkmYjHanQo) {
        Page<TKmYjHandleVo> page = new Page<>(tkmYjHanQo.getStart(), tkmYjHanQo.getSize());
        IPage<TKmYjHandleVo> result = this.getBaseMapper().pageTKmYjHandle(page, tkmYjHanQo);
        handleTKmYjInfo(result.getRecords());
        return result;
    }


    /**
     * 处理预警信息
     *
     * @param result
     */
    private void handleTKmYjInfo(List<TKmYjHandleVo> result) {
        for (TKmYjHandleVo t : result) {
            if (null == t.getYjbs()) {
                continue;
            }
            List<KmZdryTypeEntity> zdries = kmZdryTypeService.getZdryTypeBySfzh(t.getYjbs());
            if (zdries.size() > 0) {
                StringBuilder rylbx = new StringBuilder();
                StringBuilder xl = new StringBuilder();
                for (KmZdryTypeEntity zt : zdries) {
                    if (rylbx.length() > 0) {
                        rylbx.append("/").append(zt.getRylb());
                    } else {
                        rylbx.append(zt.getRylb());
                    }
                    if (xl.length() > 0) {
                        xl.append("/").append(zt.getXl());
                    } else {
                        xl.append(zt.getXl());
                    }
                }
                t.setRylbx(rylbx.toString());
                t.setXl(xl.toString());
            }
            if (null != t.getTKmYjHandleEntity() && null != t.getTKmYjHandleEntity().getId()) {
                t.getTKmYjHandleEntity().setFiles(tTaskFileService.list(new QueryWrapper<TTaskFileEntity>().lambda()
                        .eq(TTaskFileEntity::getBussType, "4").eq(TTaskFileEntity::getBussId, t.getTKmYjHandleEntity().getId())));
            }
        }
    }

    @Override
    public Mono<DataBuffer> exportYjHandleInfo(TkmYjHanQo tkmYjHanQo, String exportName) {
        DefaultDataBuffer dataBuffer = new DefaultDataBufferFactory().allocateBuffer();
        OutputStream outputStream = dataBuffer.asOutputStream();
        // 每次写100行数据，就刷新数据出缓存
        SXSSFWorkbook wb = new SXSSFWorkbook(100);

        CellStyle cellStyleCenter = wb.createCellStyle();
        CellStyle cellStyleLeft = wb.createCellStyle();
        // 居中
        cellStyleCenter.setAlignment(HorizontalAlignment.CENTER);
        cellStyleCenter.setVerticalAlignment(VerticalAlignment.CENTER);
        cellStyleLeft.setAlignment(HorizontalAlignment.LEFT);
        cellStyleLeft.setVerticalAlignment(VerticalAlignment.CENTER);

        SXSSFSheet sh = wb.createSheet(exportName == null ? "重点人员预警处置信息" : exportName);
        sh.trackAllColumnsForAutoSizing();

        List<TKmYjHandleVo> tKmYjHandleVoList = this.getBaseMapper().listTKmYjHandle(tkmYjHanQo);
        handleYjExeclData(tKmYjHandleVoList);

        int totalSize = 2 + tKmYjHandleVoList.size();
        for (int rowNum = 0; rowNum < totalSize; rowNum++) {
            Row row = sh.createRow(rowNum);
            for (int i = 0; i < exectTitle.size(); i++) {
                Cell cell = row.createCell(i);
                if (rowNum == 1) {
                    cell.setCellValue(exectTitle.get(i));
                    cell.setCellStyle(cellStyleLeft);
                }
                if (rowNum > 1) {
                    TKmYjHandleVo data = tKmYjHandleVoList.get(rowNum - 2);
                    switch (i) {
                        case 0:
                            cell.setCellValue(data.getRyxm());
                            break;
                        case 1:
                            cell.setCellValue(data.getYjsj());
                            break;
                        case 2:
                            cell.setCellValue(ZdryYjLx.YJLX.get(data.getYjlx()));
                            break;
                        case 3:
                            cell.setCellValue(data.getGkjb());
                            break;
                        case 4:
                            cell.setCellValue(data.getYjdd());
                            break;
                        case 5:
                            cell.setCellValue(data.getYjbs());
                            break;
                        case 6:
                            cell.setCellValue(data.getHjd());
                            break;
                        case 7:
                            cell.setCellValue(data.getRylbx());
                            break;
                        case 8:
                            cell.setCellValue(data.getXl());
                            break;
                        case 9:
                            cell.setCellValue(data.getSspcs());
                            break;
                        case 10:
                            cell.setCellValue(data.getGkmj());
                            break;
                        case 11:
                            cell.setCellValue(findHandleStateByHandleFlag(data.getHandleFlag()));
                            break;
                        case 12: {
                            if (null != data.getTKmYjHandleEntity()) {
                                cell.setCellValue(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(data.getTKmYjHandleEntity().getHandleTime()));
                            }
                        }
                        break;
                        case 13: {
                            if (null != data.getTKmYjHandleEntity()) {
                                cell.setCellValue(data.getTKmYjHandleEntity().getHandleResult());
                            }
                        }
                        break;
                    }
                    cell.setCellStyle(cellStyleLeft);
                }
            }
            if (rowNum == 0) {
                sh.addMergedRegion(new CellRangeAddress(0, 0, 0, 9));
                StringBuilder sb = new StringBuilder("重点人员预警处置信息");

                sh.getRow(rowNum).getCell(0).setCellValue(sb.toString());
                //设置单元格样式
                sh.getRow(rowNum).getCell(0).setCellStyle(cellStyleCenter);
            }

        }
        try {
            wb.write(outputStream);
        } catch (IOException e) {
            log.debug("导出时发生异常：==>{}", e.getMessage());
        } finally {
            try {
                wb.close();
                outputStream.flush();
                outputStream.close();
            } catch (IOException e) {
                log.debug("导出时发生异常：==>{}", e.getMessage());
            }
        }
        return Mono.just(dataBuffer);
    }

    /**
     * 处理execl导出数据
     *
     * @param result
     */
    public void handleYjExeclData(List<TKmYjHandleVo> result) {
        for (TKmYjHandleVo t : result) {
            if (null == t.getYjbs()) continue;
            List<KmZdryTypeEntity> zdries = kmZdryTypeService.getZdryTypeBySfzh(t.getYjbs());
            if (zdries.size() > 0) {
                StringBuilder rylbx = new StringBuilder();
                StringBuilder xl = new StringBuilder();
                for (KmZdryTypeEntity zt : zdries) {
                    if (rylbx.length() > 0) {
                        rylbx.append("/").append(zt.getRylb());
                    } else {
                        rylbx.append(zt.getRylb());
                    }
                    if (xl.length() > 0) {
                        xl.append("/").append(zt.getXl());
                    } else {
                        xl.append(zt.getXl());
                    }
                }
                t.setRylbx(rylbx.toString());
                t.setXl(xl.toString());
            }
        }
    }

    @Override
    public Map<String, Object> pushYjHandleInfo(Integer offset, Integer pageSize) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            Page<TKmYjHandleEntity> page = new Page<>(offset, pageSize);
            IPage<TKmYjHandleEntity> result = this.page(page);
            resultMap.put("total", result.getTotal());
            List<Map<String, Object>> records = new ArrayList<>();
            for (TKmYjHandleEntity t : result.getRecords()) {
                Map<String, Object> map = new HashMap<>();
                map.put("hanContext", t.getHandleContent());
                map.put("hanPoliceStation", t.getPoliceStation());
                map.put("hanPolice", t.getHandlePolice());
                map.put("hanPoliceStationId", t.getPoliceStationId());
                map.put("hanTime", t.getHandleTime());
                map.put("yjCode", t.getRefId());
                records.add(map);
            }
            resultMap.put("records", records);
        } catch (Exception e) {
            log.error("推送接口发生异常======>{}", e.getMessage());
        }
        return resultMap;
    }

    private String findHandleStateByHandleFlag(Integer handleFlag) {
        if (null == handleFlag) {
            return "";
        }
        String result = null;
        switch (handleFlag) {
            case 1:
                result = "未处置";
                break;
            case 2:
                result = "已处置";
                break;
            default:
                result = "";
                break;
        }
        return result;
    }

    private ResultDto pushYjHandleResultToKd(ZdryYjHandlePushDto zdryYjHandlePushDto) {
        try {
            ResponseEntity<ResultDto> responseEntity = restTemplate.postForEntity(systemConfig.getYjHandleFackUrl(), zdryYjHandlePushDto, ResultDto.class);
            ResultDto resultDto = responseEntity.getBody();
            log.info("预警反馈结果：" + resultDto.toString());
            return resultDto;
        } catch (RestClientException e) {
            log.error("推送反馈时发生异常：==》{}", e.getMessage());
        }
        return null;
    }

}
